package org.tloss.web.editor.database.editors;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.List;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResourceChangeListener;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.layout.TreeColumnLayout;
import org.eclipse.jface.viewers.CheckStateChangedEvent;
import org.eclipse.jface.viewers.CheckboxTreeViewer;
import org.eclipse.jface.viewers.ColumnLabelProvider;
import org.eclipse.jface.viewers.ColumnWeightData;
import org.eclipse.jface.viewers.ICheckStateListener;
import org.eclipse.jface.viewers.ICheckStateProvider;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.TreeViewerColumn;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeColumn;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IEditorSite;
import org.eclipse.ui.IFileEditorInput;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.part.EditorPart;
import org.tloss.web.editor.Utils;
import org.tloss.web.editor.database.editors.jdbc.Table;
import org.tloss.web.editor.enity.service.GenerateEntity;
import org.tloss.web.editor.enity.service.GenerateEntityFactory;
import org.tloss.web.editor.model.Database;
import org.tloss.web.editor.utils.Constants;

public class TableEditor extends EditorPart {

	IResourceChangeListener dirtyListener;

	public void setDirtyListener(IResourceChangeListener dirtyListener) {
		this.dirtyListener = dirtyListener;
	}

	Database database = null;

	public void setDatabase(Database database) {
		this.database = database;
		treeViewer.setInput(database);
		treeViewer.refresh();
	}

	private boolean dirty = false;
	CheckboxTreeViewer treeViewer;

	public void doSave(IProgressMonitor monitor) {
		IEditorInput editorInput = this.getEditorInput();
		IFileEditorInput fileEditorInput = (IFileEditorInput) editorInput;
		IFile file = fileEditorInput.getFile();
		JAXBContext context;
		try {
			context = JAXBContext.newInstance(Database.class);
			Marshaller marshaller = context.createMarshaller();
			ByteArrayOutputStream arrayOutputStream = new ByteArrayOutputStream();
			marshaller.marshal(database, arrayOutputStream);

			file.setContents(
					new ByteArrayInputStream(arrayOutputStream.toByteArray()),
					false, true, monitor);
			this.dirty = false;
			this.firePropertyChange(IEditorPart.PROP_DIRTY);
		} catch (JAXBException e) {
			Utils.logError("Can't save database", e);
		} catch (CoreException e) {
			Utils.logError("Can't save database", e);

		}

	}

	public void doSaveAs() {

	}

	public void init(IEditorSite site, IEditorInput input)
			throws PartInitException {
		if (!(input instanceof IFileEditorInput)) {
			throw new PartInitException("Input must be a file");
		}
		setSite(site);
		setInput(input);
	}

	public boolean isDirty() {
		return dirty;
	}

	public boolean isSaveAsAllowed() {

		return false;
	}

	public void createPartControl(Composite parent) {
		Composite composite = new Composite(parent, SWT.NONE);
		GridLayout layout = new GridLayout();
		composite.setLayout(layout);
		layout.numColumns = 2;

		Composite treeContainer = new Composite(composite, SWT.BORDER);
		GridData gridData = new GridData();
		treeContainer.setLayoutData(gridData);
		gridData.horizontalAlignment = SWT.FILL;
		gridData.grabExcessHorizontalSpace = true;
		gridData.verticalAlignment = SWT.FILL;
		gridData.grabExcessVerticalSpace = true;
		TreeColumnLayout treeLayout = new TreeColumnLayout();
		treeContainer.setLayout(treeLayout);
		treeViewer = new CheckboxTreeViewer(treeContainer, SWT.MULTI
				| SWT.FULL_SELECTION);
		Tree tree = treeViewer.getTree();
		tree.setHeaderVisible(true);

		TreeColumn valueColumn;

		valueColumn = new TreeColumn(tree, SWT.NONE);
		valueColumn.setText("Table");
		treeLayout.setColumnData(valueColumn, new ColumnWeightData(2));

		treeViewer.setContentProvider(new TableListContentProvider());
		treeViewer.setCheckStateProvider(new ICheckStateProvider() {
			@Override
			public boolean isGrayed(Object element) {

				return false;
			}

			@Override
			public boolean isChecked(Object element) {

				return (database.getTables() != null && database.getTables()
						.contains(element));
			}
		});
		// final SchemaLableProvider treeLabelProvider = new
		// SchemaLableProvider();
		// treeViewer.setLabelProvider(treeLabelProvider);

		TreeViewerColumn column2 = new TreeViewerColumn(treeViewer, valueColumn);

		column2.setLabelProvider(new ColumnLabelProvider() {
			public String getText(Object element) {
				if (element instanceof Table) {
					return ((Table) element).getTableName();
				}
				return "";
			}

			public Image getImage(Object element) {

				return Constants.TABLE_IMAGE;
			}
		});

		getSite().setSelectionProvider(treeViewer);

		treeViewer.setInput(database);

		treeViewer.setAutoExpandLevel(TreeViewer.ALL_LEVELS);
		treeViewer.addCheckStateListener(new ICheckStateListener() {

			@Override
			public void checkStateChanged(CheckStateChangedEvent event) {
				if (event.getChecked()) {
					List<Table> tables = database.getTables();
					if (tables == null) {
						tables = new ArrayList<Table>();
						database.setTables(tables);
					}
					if (!tables.contains(event.getElement())) {
						tables.add((Table) event.getElement());
						if (dirtyListener != null) {
							dirtyListener.resourceChanged(null);
						}
					}
				} else {
					List<Table> tables = database.getTables();
					if (tables == null) {
						tables = new ArrayList<Table>();
						database.setTables(tables);
					}
					if (tables.contains(event.getElement())) {
						tables.remove((Table) event.getElement());
						if (dirtyListener != null) {
							dirtyListener.resourceChanged(null);
						}
					}
				}
			}
		});

		Composite wrapper = new Composite(composite, SWT.NONE);
		RowLayout rowLayout = new RowLayout();
		wrapper.setLayout(rowLayout);
		rowLayout.type = SWT.VERTICAL;

		final Button button = new Button(wrapper, SWT.NONE);
		button.setText("Select All");

		button.addMouseListener(new MouseListener() {

			public void mouseUp(MouseEvent e) {

			}

			@SuppressWarnings("deprecation")
			public void mouseDown(MouseEvent e) {
				treeViewer.setAllChecked(true);
				Object[] objects = treeViewer.getCheckedElements();
				if (database.getTables() != null) {
					database.getTables().clear();
				} else {
					database.setTables(new ArrayList<Table>());
				}
				if (objects != null && objects.length > 0) {
					for (int i = 0; i < objects.length; i++) {
						database.getTables().add((Table) objects[i]);
					}
				}
				if (dirtyListener != null) {
					dirtyListener.resourceChanged(null);
				}
			}

			public void mouseDoubleClick(MouseEvent e) {

			}
		});
		final Button button2 = new Button(wrapper, SWT.NONE);
		button2.setText("Deselect All");

		button2.addMouseListener(new MouseListener() {

			public void mouseUp(MouseEvent e) {

			}

			@SuppressWarnings("deprecation")
			public void mouseDown(MouseEvent e) {
				treeViewer.setAllChecked(false);
				if (database.getTables() != null) {
					database.getTables().clear();
					if (dirtyListener != null) {
						dirtyListener.resourceChanged(null);
					}
				}
			}

			public void mouseDoubleClick(MouseEvent e) {

			}
		});
		final Button button3 = new Button(wrapper, SWT.NONE);
		button3.setText("Generate Enities");

		button3.addMouseListener(new MouseListener() {

			public void mouseUp(MouseEvent e) {

			}

			public void mouseDown(MouseEvent e) {
				Job job = new Job("Generate Enities") {
					protected IStatus run(IProgressMonitor monitor) {
						IProject project = ((IFileEditorInput) getEditorInput())
								.getFile().getProject();
						List<Table> tables = database.getTables();
						if (tables != null) {
							GenerateEntityFactory entityFactory = GenerateEntityFactory
									.getInstance();
							GenerateEntity generateEntity = entityFactory
									.getGenerateEntity(database);
							if (generateEntity != null) {
								for (int i = 0; i < tables.size(); i++) {
									IFile file = project.getFile("/"
											+ Constants.ENTITY_FOLDER + "/"
											+ tables.get(i).getTableName()
											+ ".empe");
									JAXBContext context;
									ByteArrayOutputStream arrayOutputStream = new ByteArrayOutputStream();
									try {
										context = JAXBContext
												.newInstance(Table.class);
										Marshaller marshaller = context
												.createMarshaller();
										marshaller.marshal(generateEntity
												.generate(tables.get(i)),
												arrayOutputStream);
									} catch (JAXBException e) {
										Utils.logError(
												"Generate entity is fail", e);
									}
									ByteArrayInputStream inputStream = new ByteArrayInputStream(
											arrayOutputStream.toByteArray());
									try {
										if (!file.exists()) {
											file.create(inputStream, true,
													monitor);
										} else {

											file.setContents(inputStream, true,
													false, monitor);
										}
									} catch (CoreException e) {
										Utils.logError(
												"Generate entity is fail", e);
										return Status.CANCEL_STATUS;
									}
								}
							} else {
								Utils.logInfo("Unsupport database type");
							}
						}
						return Status.OK_STATUS;
					}

				};
				job.setPriority(Job.LONG);
				job.schedule();
			}

			public void mouseDoubleClick(MouseEvent e) {

			}
		});
	}

	public void setFocus() {

	}

}
